use std::path::{Path, PathBuf};
use std::vec::IntoIter;
use std::fs::DirEntry;

/// 递归文件迭代器结构体
pub struct RecursiveFileIterator {
    // 当前目录的条目迭代器
    current_dir_iter: Option<IntoIter<DirEntry>>,

    // 待处理的子目录队列
    subdirs: Vec<PathBuf>,
}

impl RecursiveFileIterator {
    pub fn new(root: &Path) -> Result<Self, std::io::Error> {
        // 检查路径是否存在且是目录
        if !root.exists() || !root.is_dir() {
            return Err(std::io::Error::new(std::io::ErrorKind::NotFound, "目录不存在或不是目录"))
        }

        // 读取根目录并转换为迭代器
        let entries: Vec<DirEntry> = std::fs::read_dir(root)?
            .collect::<Result<Vec<DirEntry>, std::io::Error>>()?;

        Ok(Self {
            current_dir_iter: Some(entries.into_iter()),
            subdirs: Vec::new(),
        })  
    }

    pub fn is_text(path_buf: &PathBuf) -> bool {
        let suffixs = vec![".java", ".yml", ".properties", ".py", ".yaml", ".conf", ".txt",  ".md", ".rs", ".toml"];
        for suf in suffixs {
            if path_buf.to_str().unwrap().ends_with(suf) {
                return true;
            }
        }
        false
    }
}

/// 实现迭代器trait
impl Iterator for RecursiveFileIterator {
    type Item = PathBuf;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            // 检查目录迭代器是否有内容
            if let Some(iter) = &mut self.current_dir_iter {
                if let Some(entry) = iter.next() {
                    let path = entry.path();
                    if path.is_dir() {
                        self.subdirs.push(path);
                    } else {
                        if Self::is_text(&path) {
                            return Some(path);
                        }
                    }
                } else {
                    // 当前目录迭代器已耗尽，清楚它
                    self.current_dir_iter = None;
                }
            } else {
                // 当前目录迭代器已耗尽，尝试处理下一个子目录
                if let Some(subdir) = self.subdirs.pop() {
                    match std::fs::read_dir(&subdir) {
                        Ok(entries) => {
                            // 将目录条目转为迭代器
                            let entries:Vec<DirEntry> = entries.filter_map(|e| e.ok()).collect();
                            self.current_dir_iter = Some(entries.into_iter());
                        },
                        Err(e) => {
                            eprintln!("无法读取目录：{:?}: {}", subdir, e);
                        }
                    }
                } else {
                    // 没有更多子目录需要处理，迭代结束
                    return None;
                }
            }
        }
    }
}

#[cfg(test)]
mod tests { 
    use super::*;

    #[test]
    fn it_works() -> Result<(), std::io::Error>{ 
        let file_iterator = RecursiveFileIterator::new(Path::new("d:/git-repo-rust/text-search"))?;
        for (i, file_path) in file_iterator.enumerate() { 
            println!("{}: {:?}", i + 1, file_path);
        }
        Ok(())
    }
}



